import laspy
import numpy as np
from typing import Tuple, Dict, Any
import sys

class LASReader:
    def __init__(self, las_path: str):
        self.las_path = las_path
        self.las_file = None
        self.point_format = None
        
    def read_las(self) -> bool:
        try:
            with laspy.open(self.las_path) as f:
                self.las_file = f.read()
                self.point_format = self.las_file.point_format
                
                # 只访问前5个点的坐标，避免解压全部数据
                print("\n坐标示例(前5个点):")
                print("X:", self.las_file.x[:5])
                print("Y:", self.las_file.y[:5])
                print("Z:", self.las_file.z[:5])
                
                return True
        except Exception as e:
            print(f"读取LAS文件失败: {str(e)}", file=sys.stderr)
            return False

    def _get_bounds(self) -> Tuple[Tuple[float, float], Tuple[float, float], Tuple[float, float]]:
        """使用头文件中的范围信息，效率更高"""
        return (
            (self.las_file.header.mins[0], self.las_file.header.maxs[0]),
            (self.las_file.header.mins[1], self.las_file.header.maxs[1]),
            (self.las_file.header.mins[2], self.las_file.header.maxs[2])
        )
        
    def get_basic_info(self) -> Dict[str, Any]:
        if not self.las_file:
            return {}
            
        info = {
            '文件路径': self.las_path,
            '点数量': len(self.las_file.points),
            '点格式': str(self.point_format.id),
            '坐标系': self._get_coordinate_system(),
            '范围': self._get_bounds(),
            '属性字段': list(self.point_format.dimension_names),
            '分类统计': self._get_classification_stats(),
            '强度统计': self._get_intensity_stats(),
            '返回次数统计': self._get_return_stats()
        }
        
        if 'gps_time' in self.point_format.dimension_names:
            info['时间范围'] = (float(np.min(self.las_file.gps_time)), 
                             float(np.max(self.las_file.gps_time)))
            
        return info
        
    def _get_coordinate_system(self) -> str:
        try:
            crs = self.las_file.header.parse_crs()
            return crs.to_string() if crs else "未知坐标系"
        except:
            return "未知坐标系"
        
    def _get_classification_stats(self) -> Dict[int, int]:
        if 'classification' not in self.point_format.dimension_names:
            return {}
            
        unique, counts = np.unique(self.las_file.classification, return_counts=True)
        return dict(zip(unique, counts))
        
    def _get_intensity_stats(self) -> Dict[str, float]:
        if 'intensity' not in self.point_format.dimension_names:
            return {}
            
        intensity = self.las_file.intensity
        return {
            '最小值': float(np.min(intensity)),
            '最大值': float(np.max(intensity)),
            '平均值': float(np.mean(intensity)),
            '标准差': float(np.std(intensity))
        }
        
    def _get_return_stats(self) -> Dict[int, int]:
        if 'return_number' not in self.point_format.dimension_names:
            return {}
            
        unique, counts = np.unique(self.las_file.return_number, return_counts=True)
        return dict(zip(unique, counts))

if __name__ == "__main__":
    las_path = "E:\\工作资料\\las处理\\zzxtest.las"
    
    reader = LASReader(las_path)
    if reader.read_las():
        info = reader.get_basic_info()
        print("\nLAS文件基本信息:")
        for key, value in info.items():
            print(f"{key}: {value}")